package usercenterservice

import (
	"context"
	"gitee.com/go-mid/infra/xlog"
	"gitee.com/go-mid/infra/xsql/xdb"
	"gitee.com/go-mid/infra/xtime"
	"gitee.com/go-mid/usercenter/internal/component"
	"gitee.com/go-mid/usercenter/internal/dao"
	"gitee.com/go-mid/usercenter/internal/entity"
	"github.com/jinzhu/copier"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"
	"time"
)

type GetUserLogReq struct {
	ID int64 `json:"id"` //  用户日志唯一标识
} //@name 获取用户日志入参

type UserLogInfo struct {
	ID      int64  `json:"id" bdb:"id"`             //
	UserID  int64  `json:"user_id" bdb:"user_id"`   //用户id
	Ct      int64  `json:"ct" bdb:"ct"`             //创建时间
	Ut      int64  `json:"ut" bdb:"ut"`             //修改时间
	LogType int32  `json:"log_type" bdb:"log_type"` //日志类型
	Log     string `json:"log" bdb:"log"`           //日志信息

} //@name 用户日志信息

type GetUserLogRes struct {
	UserLogInfo *UserLogInfo `json:"user_log_info"`
} //@name 获取用户日志响应

func (m *UsercenterServiceImpl) GetUserLog(ctx context.Context, req *GetUserLogReq) (res *GetUserLogRes, err error) {
	fun := "UsercenterServiceImpl.GetUserLog -->"
	st := xtime.NewTimeStat()
	defer func() {
		xlog.Infow(ctx, fun, "durationMs", st.Millisecond(), "req", req, "res", res, "err", err)
	}()
	//这里 不能是空指针
	item, err := dao.GetUserLog(ctx, component.XDBUsercenter, req.ID)
	if err != nil {
		xlog.Warnf(ctx, "%s dao.GetUserLog err: req: %v, err: %v", fun, req, err)
		err = status.Error(codes.Internal, err.Error())
		return
	}
	if item == nil {
		return nil, nil
	}
	res = &GetUserLogRes{
		UserLogInfo: m.toUserLogInfo(ctx, item),
	}
	return
}

func (m *UsercenterServiceImpl) toUserLogInfo(ctx context.Context, item *entity.UserLog) *UserLogInfo {
	if item == nil {
		return nil
	}
	var info UserLogInfo
	copier.Copy(&info, item)
	return &info
}
func (m *UsercenterServiceImpl) toUserLogInfos(ctx context.Context, items []*entity.UserLog) []*UserLogInfo {
	var infos = make([]*UserLogInfo, 0)
	for _, item := range items {
		infos = append(infos, m.toUserLogInfo(ctx, item))
	}
	return infos
}

type ListUserLogReq struct {
	Offset    int64 `json:"offset"`     // 下一页游标
	Limit     int64 `json:"limit"`      // 每页条数
	WithTotal bool  `json:"with_total"` // 是否查询总量
} //@name 查询用户日志入参

type ListUserLogRes struct {
	Items  []*UserLogInfo `json:"items"`
	Offset int64          `json:"offset"`
	More   bool           `json:"more"`
	Total  int            `json:"total"`
} //@name 查询用户日志响应

func (m *UsercenterServiceImpl) ListUserLog(ctx context.Context, req *ListUserLogReq) (res *ListUserLogRes, err error) {
	fun := "UsercenterServiceImpl.ListUserLog -->"
	st := xtime.NewTimeStat()
	defer func() {
		xlog.Infow(ctx, fun, "durationMs", st.Millisecond(), "req", req, "res", res, "err", err)
	}()
	var items []*entity.UserLog
	var offset = req.Offset
	var limit = req.Limit
	if offset < 0 {
		offset = 0
	}
	if limit < 1 || limit > 1000 {
		limit = 1000
	}
	var where = map[string]interface{}{
		//	todo where条件
		"_limit":   []int64{offset, limit + 1},
		"_orderby": "ct desc",
	}
	err = component.XDBUsercenter.Select(ctx, entity.UserLogTable, where, &items)
	if err != nil {
		xlog.Warnf(ctx, "%s select err: req: %v, err: %v", fun, req, err)
		err = status.Error(codes.Internal, err.Error())
		return
	}
	var more bool
	if len(items) > int(limit) {
		items = items[0:limit]
		more = true
	}
	offset = offset + int64(len(items))
	var total int
	if req.WithTotal {
		delete(where, "_limit")
		delete(where, "_orderby")
		cnt, err := component.XDBUsercenter.SelectCount(ctx, entity.UserLogTable, where)
		if err != nil {
			xlog.Warnf(ctx, "%s count err: req: %v, err: %v", fun, req, err)
			err = status.Error(codes.Internal, err.Error())
			return nil, err
		}
		total = cnt
	}
	res = &ListUserLogRes{
		Items:  m.toUserLogInfos(ctx, items),
		Offset: offset,
		More:   more,
		Total:  total,
	}
	return
}

type AddUserLogReq struct {
	UserID  int64  `json:"user_id" bdb:"user_id"`   //用户id
	LogType int32  `json:"log_type" bdb:"log_type"` //日志类型
	Log     string `json:"log" bdb:"log"`           //日志信息

} //@name 添加用户日志入参

type AddUserLogRes struct {
	ID int64 `json:"id"`
} //@name 添加用户日志入参

func (m *UsercenterServiceImpl) AddUserLog(ctx context.Context, req *AddUserLogReq) (res *AddUserLogRes, err error) {
	fun := "UsercenterServiceImpl.AddUserLog -->"
	st := xtime.NewTimeStat()
	defer func() {
		xlog.Infow(ctx, fun, "durationMs", st.Millisecond(), "req", req, "res", res, "err", err)
	}()
	var item entity.UserLog
	copier.Copy(&item, req)
	//todo  构建inert对象
	now := time.Now().Unix()
	item.Ct = now
	item.Ut = now
	ups, err := xdb.BuildDbSqlMap(ctx, &item, false)
	if err != nil {
		xlog.Warnf(ctx, "%s build sql err: req: %v, err: %v", fun, req, err)
		err = status.Error(codes.Internal, err.Error())
		return
	}
	newID, err := component.XDBUsercenter.Insert(ctx, entity.UserLogTable, []map[string]interface{}{
		ups,
	})
	if err != nil {
		xlog.Errorf(ctx, "%s add db error: req: %v, err: %v", fun, req, err)
		err = status.Error(codes.Internal, err.Error())
		return
	}
	res = &AddUserLogRes{
		ID: int64(newID),
	}
	return
}

type UpdateUserLogReq struct {
	ID      int64  `json:"id" bdb:"id"`             //
	UserID  int64  `json:"user_id" bdb:"user_id"`   //用户id
	LogType int32  `json:"log_type" bdb:"log_type"` //日志类型
	Log     string `json:"log" bdb:"log"`           //日志信息

} //@name 修改用户日志入参

type UpdateUserLogRes struct {
} //@name 修改用户日志响应

func (m *UsercenterServiceImpl) UpdateUserLog(ctx context.Context, req *UpdateUserLogReq) (res *UpdateUserLogRes, err error) {
	fun := "UsercenterServiceImpl.UpdateUserLog -->"
	st := xtime.NewTimeStat()
	defer func() {
		xlog.Infow(ctx, fun, "durationMs", st.Millisecond(), "req", req, "res", res, "err", err)
	}()
	var item entity.UserLog
	copier.Copy(&item, req)
	now := time.Now().Unix()
	item.Ut = now
	ups, err := xdb.BuildSqlMap(ctx, &item, xdb.BuildOption{
		OmitZero:       true,
		ExcludeColumns: []string{"id"},
	})
	if err != nil {
		xlog.Warnf(ctx, "%s build sql err: req: %v, err: %v", fun, req, err)
		err = status.Error(codes.Internal, err.Error())
		return
	}
	_, err = component.XDBUsercenter.Update(ctx, entity.UserLogTable, map[string]interface{}{
		"id": req.ID,
	}, ups)
	if err != nil {
		xlog.Errorf(ctx, "%s update db error: req: %v, err: %v", fun, req, err)
		err = status.Error(codes.Internal, err.Error())
		return
	}
	res = &UpdateUserLogRes{}
	return
}

type UpsertUserLogReq struct {
	ID      int64  `json:"id" bdb:"id"`             //
	UserID  int64  `json:"user_id" bdb:"user_id"`   //用户id
	LogType int32  `json:"log_type" bdb:"log_type"` //日志类型
	Log     string `json:"log" bdb:"log"`           //日志信息

} //@name 添加或修改用户日志入参

type UpsertUserLogRes struct {
	ID int64 `json:"id"`
} //@name 添加或修改用户日志响应

func (m *UsercenterServiceImpl) UpsertUserLog(ctx context.Context, req *UpsertUserLogReq) (res *UpsertUserLogRes, err error) {
	fun := "UsercenterServiceImpl.UpsertUserLog -->"
	st := xtime.NewTimeStat()
	defer func() {
		xlog.Infow(ctx, fun, "durationMs", st.Millisecond(), "req", req, "res", res, "err", err)
	}()
	if req.ID > 0 {
		var upReq UpdateUserLogReq
		copier.Copy(&upReq, req)
		_, err = m.UpdateUserLog(ctx, &upReq)
		if err != nil {
			xlog.Warnf(ctx, "%s UpdateUserLog err: req: %v, err: %v", fun, req, err)
			return
		}
		res = &UpsertUserLogRes{
			ID: req.ID,
		}
		return
	}
	var addReq AddUserLogReq
	copier.Copy(&addReq, req)
	addRes, err := m.AddUserLog(ctx, &addReq)
	if err != nil {
		xlog.Warnf(ctx, "%s AddUserLog err: req: %v, err: %v", fun, req, err)
		return
	}
	res = &UpsertUserLogRes{
		ID: addRes.ID,
	}
	return
}
